package net;

import interfaces.IClientReciever;
import interfaces.IClientSender;
import interfaces.IGameManagement;

import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import valueObjects.game.Player;
import valueObjects.game.card.Card;
import valueObjects.game.card.door.CharacterClassCard;
import valueObjects.game.card.door.CharacterRaceCard;
import valueObjects.game.card.door.MonsterCard;
import valueObjects.game.card.treasure.EquipmentCard;
import valueObjects.game.card.treasure.MiscellaneousCard;
import exception.equipment.NotEquipable;

public class ClientSession extends UnicastRemoteObject implements IClientSender {

	private static final long serialVersionUID = 1L;
	
	private GameManagement server;
	private IClientReciever handle;

	private Player player;
	
	/**
	 * Constructor
	 * @throws RemoteException
	 */
	protected ClientSession() throws RemoteException {
	}
	/**
	 * Constructor
	 * @param p
	 * @param gameManagment
	 * @param handle
	 * @throws RemoteException
	 */
	public ClientSession(Player p, GameManagement gameManagement, IClientReciever handle) throws RemoteException {
		this.server = gameManagement;
		this.handle = handle;
		this.player = p;
	}
	/**
	 * Sender for Card
	 * @param c
	 * @throws RemoteException
	 */
	@Override
	public void sendCard(Card c) throws RemoteException {
		server.postCard(c);
	}
	/**
	 * Getter for IClientReciever
	 * @return this.handle
	 */
	public IClientReciever getClientHandle() {
		return this.handle;
	}

	/**
	 * Sender for starting Game
	 * @throws RemoteException
	 */
	@Override
	public void sendStartGame() throws RemoteException {
		server.startGame();
	}

	/**
	 * Sender for chatMessages
	 * @param message
	 * @throws RemoteException
	 */
	@Override
	public void sendMessage(String message) throws RemoteException {
		server.postMessage(player.getName(), message);
	}


	/**
	 * Getter for Player
	 * @return this.player
	 *
	 */
	public Player getPlayer() {
		return this.player;
	}

	/**
	 * Sender for addMiscellaneous
	 * @param eCard
	 * @throws RemoteException
	 * @throws NotEquipable
	 */
	@Override
	public void addMiscellaneuos(MiscellaneousCard eCard)
			throws NotEquipable, RemoteException {
		server.addMiscellaneuos(this.player, eCard);
	}

	/**
	 * Sender for finish
	 * @param eCard
	 * @throws RemoteException
	 */
	@Override
	public void finish() throws RemoteException, IOException {
		this.server.finish(this.player);
	}
	
	/**
	 * Sender for combat
	 * @param monsterCard
	 * @throws RemoteException
	 * @throws InterruptedException
	 * @return win
	 */
	@Override
	public boolean combat(MonsterCard monsterCard) throws RemoteException, InterruptedException {
		boolean win = this.server.combat(this.player, monsterCard);
		short interaction = 0;
		while(win && interaction > 0){
			for (IClientSender p : this.server.getSessions()) {
				 if(this.server.askForInteraction(p.getPlayer())){
					 interaction++;	
				}
			}
			if(interaction > 0){
				win = this.server.interaction(this.player, monsterCard);
			}
		}
		return win;
	}

	/**
	 * Sender for changeEquipment
	 * @param slot
	 * @param equipmentCard
	 * @throws RemoteException
	 * @throws NotEquipable
	 */
	@Override
	public void changeEquipment(String slot, EquipmentCard equipmentCard) throws RemoteException, NotEquipable {
		this.server.changeEquipment(this.player, slot, equipmentCard);
	}
	/**
	 * Sender for askForInteraction
	 * @throws RemoteException
	 * @throws InterruptedException
	 */
	@Override
	public boolean askForInteraction() throws RemoteException, InterruptedException {
		return this.server.askForInteraction(this.player);
	}

	/**
	 * Sender for askForHelp
	 * @throws RemoteException
	 * @throws InterruptedException
	 */
	@Override
	public boolean askForHelp() throws RemoteException, InterruptedException {
		return this.server.askForHelp(this.player);
	}

	/**
	 * Sender for flee
	 * @param c
	 * @throws RemoteException
	 */
	@Override
	public void flee(MonsterCard c) throws RemoteException {
		this.server.flee(this, c);
	}
	@Override
	public void addCard(Card c) throws RemoteException {
		this.player.addCard(c);
	}
	@Override
	public void removeCard(Card card) throws RemoteException {
		this.player.removeCard(card);
	}
	public void setPlayer(Player player) {
		this.player = player;
	}
	@Override
	public void addCardInteractAgainst(MonsterCard mCard)
			throws RemoteException {
		this.player.addCardInteractAgainst(mCard);
	}
	@Override
	public void setCharacterRace(CharacterRaceCard equipmentCard)
			throws RemoteException {
		this.player.setCharacterRace(equipmentCard);
	}
	@Override
	public void setCharacterClass(CharacterClassCard equipmentCard)
			throws RemoteException {
		this.player.setCharacterClass(equipmentCard);
	}
	@Override
	public boolean askForSave() throws RemoteException {
		return this.server.askForSave(this);
	}
	@Override
	public void prepare(IGameManagement server) throws RemoteException {
		boolean prepared = false;
		if(server != null){
			for (IClientSender sess : server.getSessions()) {
				if(sess.getPlayer().equals(this.player) && sess.getPlayer().getHandCards().size() > 0){
					this.player = sess.getPlayer();
					prepared = true;
				}
			}
		} else {
			if(!prepared){
				for (int i = 0; i < 2; i++) {
					this.player.addCard(this.server.getOneCardFromDoorPickUpStack());
					this.player.addCard(this.server.getOneCardFromTreasurePickUpStack());
				}	
			}
		}
	}
	@Override
	public void sendWaitForCard() throws RemoteException {
		this.server.waitForCard(this);
	}

}
